using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using System.Reflection;
using System.Xml;
using System.Web.UI.HtmlControls;

using Pampa.CRUD.Core;
using Pampa.CRUD.Utils;
using Pampa.WebControls;

namespace Pampa.CRUD.UI.CustomControls
{
    [ToolboxData("<{0}:EntitySelector runat=server></{0}:EntitySelector>")]
    [DesignerAttribute(typeof(BaseDesigner), typeof(System.ComponentModel.Design.IDesigner))]
    public class EntitySelector : Selector
    {
        string entityName;
        string parentId;
        string foreingProperty;

        public EntitySelector()
        {
            this.dataHandler = "EntitySelector_GetList";
            this.clientClass = "WebEntitySelector";
        }

        #region Properties

        public new string DataHandler
        {
            get
            {
                return dataHandler;
            }
        }

        public string EntityName
        {
            get { return entityName; }
            set { entityName = value; }
        }

        /// <summary>
        /// Id del combo padre. Esta propiedad permite enlazar los combos.
        /// </summary>
        public string ParentId
        {
            get { return parentId; }
            set { parentId = value; }
        }

        /// <summary>
        /// Propiedad que debera matchear con el valor del combo padre.
        /// </summary>
        public string ForeingProperty
        {
            get { return foreingProperty; }
            set { foreingProperty = value; }
        }

        public string PropertyId
        {
            get;
            set;
        }

        public string PropertyDescription
        {
            get;
            set;
        }

        #endregion

        #region Load

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            Ajax.Utility.RegisterTypeForAjax(typeof(EntitySelector));
            RegisterLibrary("Pampa.CRUD/EntityRelationships.js");
            RegisterLibrary("Pampa.CRUD/EntitySelector.js");
        }

        #endregion

        #region Render

        protected override void RenderProperties(HtmlTextWriter output)
        {
            base.RenderProperties(output);

            output.WriteLine(this.ObjectName + ".entityName = '" + this.EntityName + "';");

            if (!String.IsNullOrEmpty(this.ForeingProperty))
                output.WriteLine(this.ObjectName + ".foreingProperty = '" + this.ForeingProperty + "';");

            if (!String.IsNullOrEmpty(this.PropertyId))
                output.WriteLine(this.ObjectName + ".propertyId = '" + this.PropertyId + "';");

            if (!String.IsNullOrEmpty(this.PropertyDescription))
                output.WriteLine(this.ObjectName + ".propertyDescription = '" + this.PropertyDescription + "';");

            if (!String.IsNullOrEmpty(this.ParentId))
            {
                RenderRelationship(output);
            }
        }

        private void RenderRelationship(HtmlTextWriter output)
        {
            output.WriteLine("EntitySelector_RegisterRelationship('" + this.parentId + "', '" + this.ID + "')");

            SetParentValue(output);
        }

        protected void SetParentValue(HtmlTextWriter output)
        {
            if (!String.IsNullOrEmpty(this.ParentId))
            {
                Control parentControl = ControlFinder.FindParentOf(this, this.ParentId);
                
                String parentValue = null;

                if (parentControl != null)
                {
                    if (parentControl is EntityComboList)
                    {
                        parentValue = ((EntityComboList)parentControl).Value;
                    }
                    else if (parentControl is EntitySelector)
                    {
                        parentValue = ((EntitySelector)parentControl).Value;
                    }
                    else if (parentControl is HiddenField)
                    {
                        parentValue = ((HiddenField)parentControl).Value;
                    }
                    else if (parentControl is HtmlInputHidden)
                    {
                        parentValue = ((HtmlInputHidden)parentControl).Value;
                    }
                    else if ( (parentControl is DatePicker) && (((DatePicker)parentControl).Date.HasValue) )
                    {
                        parentValue = ((DatePicker)parentControl).Date.ToString();
                    }

                    if (parentValue != null)
                        output.WriteLine(this.ObjectName + ".parentValue = '" + parentValue + "';");
                }
            }
        }

        #endregion

        #region Ajax Functions

        [Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
        public static string GetList(string controlId, string entityName, string value, int maxtam, string propertyId, string propertyDesc)
        {
            // Pido la lista de items al EntityManager
            // pido uno de mas para chequear si hay mas o no 
            IList list = EntityManager.GetList(controlId, entityName, propertyDesc, value, maxtam + 1); 
            SelectorResponse res = new SelectorResponse(value, list.Count > maxtam);

            try
            {
                int i = 0;

                foreach (var item in list)
                {
                    if (i < maxtam)
                    {
                        if (item is IIdDescription)
                        {
                            var aitem = (IIdDescription)item;
                            res.AddItem(aitem.Id.Trim(), aitem.Description.Trim());
                        }
                        else
                        {
                            var id = EntityManager.GetPropertyValue(item, propertyId).ToString();
                            var desc = EntityManager.GetPropertyValue(item, propertyDesc);
                            var descStr = (desc != null) ? desc.ToString() : null;
                            res.AddItem(id, descStr);
                        }
                    }

                    i++;
                }
            }
            catch (Exception ex)
            {
                throw (new Exception("Unexpected Error trying to build a list of " + entityName + ".", ex));
            }

            return res.Document.OuterXml;
        }

        [Ajax.AjaxMethod(Ajax.HttpSessionStateRequirement.ReadWrite)]
        public static string GetFilteredList(string controlId, string entityName, string value, int maxtam, string property, string parentValue, string propertyId, string propertyDesc)
        {
            // Pido la lista de items al EntityManager
            // pido uno de mas para chequear si hay mas o no 
            IList list = EntityManager.GetList(controlId, entityName, propertyDesc, value, maxtam + 1, property, parentValue); 
            SelectorResponse res = new SelectorResponse(value, list.Count > maxtam);

            try
            {
                int i = 0;

                foreach (var item in list)
                {
                    if (i < maxtam)
                    {
                        if (item is IIdDescription)
                        {
                            var aitem = (IIdDescription)item;
                            res.AddItem(aitem.Id.Trim(), aitem.Description.Trim());
                        }
                        else
                        {
                            var id = EntityManager.GetPropertyValue(item, propertyId).ToString();
                            var desc = EntityManager.GetPropertyValue(item, propertyDesc);
                            var descStr = (desc != null) ? desc.ToString() : null;
                            res.AddItem(id, descStr);
                        }
                    }

                    i++;
                }
            }
            catch (Exception ex)
            {
                throw (new Exception("Unexpected Error trying to build a list of " + entityName + ".", ex));
            }

            return res.Document.OuterXml;
        }

        #endregion
    }
}
